package com.itheima.reggie.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.common.PageBean;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.*;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.util.ExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DishServiceImpl implements DishService {

    @Autowired(required = false)
    private DishMapper dishMapper;

    @Autowired(required = false)
    private CategoryMapper categoryMapper;

    @Autowired(required = false)
    private DishFlavorMapper dishFlavorMapper;

    @Autowired(required = false)
    private SalesMapper salesMapper;

    @Autowired(required = false)
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${reggie.path}")
    private String basePath;
    /**
     * 分页条件查询所有菜品
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @Override
    public R<PageBean> findPage(int page, int pageSize, String name) {
        //1.开启分页
        PageHelper.startPage(page,pageSize);
        //2.查询Dish所有数据
        List<Dish> dishList = dishMapper.findPage(name);
        //获取分页对象
        PageInfo<Dish> pageInfo = new PageInfo<>(dishList);
        //3.遍历集合，查询每一个Dish的分类名称，封装到DishDto中
        List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : pageInfo.getList()) {
            String categoryNameById = categoryMapper.findCategoryNameById(dish.getCategoryId());
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            if (categoryNameById != null) {
                dishDto.setCategoryName(categoryNameById);
            } else {
                dishDto.setCategoryName("暂无类别");
            }

            dishDtoList.add(dishDto);
        }

        return pageInfo != null ? R.success(new PageBean(dishDtoList,pageInfo.getTotal(),pageSize,page)) : R.error("查询失败");


    }

    /**
     * 新增菜品
     *
     * @param dishDto
     * @return
     */
    @Transactional
    @Override
    public R<String> addDish(DishDto dishDto) {

        try{
            //继续补充数据，操作时间，排序,售卖状态
            dishDto.setCreateTime(LocalDateTime.now());
            dishDto.setUpdateTime(LocalDateTime.now());
            dishDto.setSort(0);
            dishDto.setStatus(1);

            //插入菜品数据，并返回主键
            dishMapper.addDish(dishDto);
            Long dishId = dishDto.getId();

            //获取DishFlavor集合
            List<DishFlavor> flavorList = dishDto.getFlavors();
            //使用java8新特性--stream流补充dishFlavor数据
            List<DishFlavor> dishFlavors = flavorList.stream().map(dishFlavor -> {
                dishFlavor.setDishId(dishId);
                dishFlavor.setCreateTime(dishDto.getCreateTime());
                dishFlavor.setUpdateTime(dishDto.getUpdateTime());
                dishFlavor.setCreateUser(dishDto.getCreateUser());
                dishFlavor.setUpdateUser(dishDto.getUpdateUser());
                return dishFlavor;
            }).collect(Collectors.toList());

            if (dishFlavors.size()>0){
                dishFlavorMapper.addBatchDishFlavor(dishFlavors);
            }

            Set keys = redisTemplate.keys("dish_*");
            redisTemplate.delete(keys);
        }catch (Exception e){
            e.printStackTrace();
            return R.error("添加失败");
        }
        return R.success("添加成功");
    }

    /**
     * 根据id查询菜品和口味信息
     *
     * @param id
     * @return
     */
    @Override
    public R<DishDto> findDishDtoById(long id) {
        DishDto dishDto = new DishDto();
        try {
            BeanUtils.copyProperties(dishMapper.findDishByDishId(id),dishDto);
            dishDto.setFlavors(dishFlavorMapper.findDishFlavorsByDishId(id));
        }catch (Exception e){
            return R.error("服务器内部错误，查询失败");
        }

        return R.success(dishDto);
    }

    /**
     * 更新菜品和口味数据
     *
     * @param dishDto
     * @return
     */
    @Transactional
    @Override
    public R<String> update(DishDto dishDto) {
        dishDto.setUpdateTime(LocalDateTime.now());
        Long dishId = dishDto.getId();
        String dbImageName = dishMapper.findImageNameById(dishId);
        if (dbImageName!=null&&dbImageName!=null){
            //服务器有值
            if (!dbImageName.equals(dishDto.getImage())){
                //图片有更新，删除旧的图片
                deleteImageByDishId(dishId);
            }
        }
        //更新菜品数据
        int updateDish = dishMapper.update(dishDto);

        int deleteDishFlavors = dishFlavorMapper.deleteByDishId(dishId);

        //删除旧的口味数据
        List<DishFlavor> flavorList = dishDto.getFlavors();
        //更新信息
        List<DishFlavor> flavors = flavorList.stream().map(dishFlavor -> {
            dishFlavor.setDishId(dishId);
            dishFlavor.setCreateTime(dishDto.getCreateTime());
            dishFlavor.setUpdateTime(dishDto.getUpdateTime());
            dishFlavor.setCreateUser(dishDto.getCreateUser());
            dishFlavor.setUpdateUser(dishDto.getUpdateUser());
            return dishFlavor;
        }).collect(Collectors.toList());
        //批量插入新的口味数据
        int batchDishFlavor = dishFlavorMapper.addBatchDishFlavor(flavors);
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
        return R.success("更新成功");
    }

    /**
     * 批量禁用菜品
     *
     * @param ids
     * @return
     */
    @Override
    public R<String> disableDish(int status,Long[] ids) {

        int result = dishMapper.updateDishStatus(status,ids);
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
        return result>0?R.success("禁用成功"):R.error("禁用失败");
    }

    /**
     * 批量删除菜品
     *
     * @param ids
     * @return
     */
    @Override
    public R<String> deleteDish(Long[] ids) {
        //查询选中的菜品是否有在售菜品
        if (dishMapper.findDishIsSaleByIds(ids)>0){
         //有在售商品无法删除
         return R.error("当前选中菜品中有在售商品，请重新选择");
        }
        //查询选中菜品中是否包含套餐

        if (setmealDishMapper.findDishIsExist(ids)>0){
            return R.error("当前选中菜品中有商品属于套餐内商品，如需删除，请先删除套餐");
        }
        for (Long id : ids) {
            deleteImageByDishId(id);
        }
        int result = dishMapper.deleteDish(ids);
        redisTemplate.delete("dish_*");

        return result>0?R.success("删除成功"):R.error("删除失败");
    }

    /**
     * 根据类别id查询菜品列表
     *
     * @param categoryId
     * @return
     */
    @Override
    public R<List<DishDto>> findDishListById(Long categoryId,Integer status) {
        ValueOperations opsForValue = redisTemplate.opsForValue();
        List<DishDto> dishDtoList = null;
        //优化：查看缓存中是否有数据，有则直接查询
        String key = "dish_"+categoryId;
        dishDtoList = (List<DishDto>) opsForValue.get(key);
        if (dishDtoList==null){
            List<Dish> dishList = dishMapper.findDishListById(categoryId,status);
            dishDtoList = new ArrayList<>();
            for (Dish dish : dishList) {
                DishDto dishDto = new DishDto();
                BeanUtils.copyProperties(dish,dishDto);
                dishDto.setFlavors(dishFlavorMapper.findDishFlavorsByDishId(dishDto.getId()));
                dishDto.setMonthlySales(salesMapper.findDishMonthlySales(dishDto.getId(),LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))));
                dishDtoList.add(dishDto);
            }
            opsForValue.set(key,dishDtoList,24, TimeUnit.HOURS);//设置24小时失效
        }
        return dishDtoList.size()>0? R.success(dishDtoList):R.error("查询失败");
    }






    /**
     * 导出所有菜品数据到Excel
     *
     * @return
     */
    @Override
    public Workbook exportExcel(long[] ids) {
        //先查询所有数据
        List<Dish> dishList = dishMapper.findDishByDishIds(ids);
        List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : dishList) {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            dishDto.setCategoryName(categoryMapper.findCategoryNameById(dish.getCategoryId()));
            dishDto.setFlavors(dishFlavorMapper.findDishFlavorsByDishId(dish.getId()));
            dishDtoList.add(dishDto);
        }

        Workbook workbook;

        try {
            //1.读取模板输入流
            InputStream inputStream = DishServiceImpl.class.getResourceAsStream("/excel/dish.xlsx");
            //2.基于输入流创建模板
            workbook = new XSSFWorkbook(inputStream);
            //3.得到模板的工作单
            Sheet sheet = workbook.getSheetAt(0);



            Row row1 = sheet.getRow(2);//样式一
            Row row2 = sheet.getRow(3);//样式二



            //4.提取样式
            CellStyle cellStyleRow1= row1.getCell(0).getCellStyle();
            CellStyle cellStyleRow2= row2.getCell(0).getCellStyle();
            cellStyleRow1.setWrapText(true);
            cellStyleRow2.setWrapText(true);


            int currentRow = 0;
            for (int i = 0; i < dishDtoList.size(); i++) {

                currentRow = i+2;

                if (currentRow % 2 == 0){

                    row1 = sheet.createRow(currentRow);
                    row1.setHeight((short)2000);

                    //序号
                    Cell cell = row1.createCell(0);
                    cell.setCellValue(dishDtoList.get(i).getId().toString());
                    cell.setCellStyle(cellStyleRow1);

                    //名称
                     cell = row1.createCell(1);
                    cell.setCellValue(dishDtoList.get(0).getName());
                    cell.setCellStyle(cellStyleRow1);

                    //图片
                    ExcelUtils.insertImage(basePath+dishDtoList.get(i).getImage(),workbook,sheet,currentRow,2);

                    //分类名称
                    cell = row1.createCell(3);
                    cell.setCellValue(dishDtoList.get(i).getCategoryName());
                    cell.setCellStyle(cellStyleRow1);

                    //售价
                    cell = row1.createCell(4);
                    cell.setCellValue(dishDtoList.get(i).getPrice().intValue()/100);
                    cell.setCellStyle(cellStyleRow1);

                    //口味

                    String flavorValue = "";
                    for (DishFlavor flavor : dishDtoList.get(i).getFlavors()) {
                        flavorValue=flavorValue +flavor.getName()+":"+flavor.getValue()+"\r\n";
                    }
                    cell = row1.createCell(5);
                    cell.setCellValue(flavorValue);
                    cell.setCellStyle(cellStyleRow1);

                    //描述
                    cell = row1.createCell(6);
                    cell.setCellValue(dishDtoList.get(i).getDescription());
                    cell.setCellStyle(cellStyleRow1);

                    //状态
                    String statusValue = "";
                    if (dishDtoList.get(i).getStatus() == 1){
                        statusValue = "启售";
                    }else {
                        statusValue = "停售";
                    }
                    cell = row1.createCell(7);
                    cell.setCellValue(statusValue);
                    cell.setCellStyle(cellStyleRow1);
                    //最后操作时间
                    cell = row1.createCell(8);
                    cell.setCellValue(dishDtoList.get(i).getUpdateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    cell.setCellStyle(cellStyleRow1);

                }else {

                    row2 = sheet.createRow(currentRow);
                    row2.setHeight((short)2000);

                    //序号
                    Cell cell = row2.createCell(0);
                    cell.setCellValue(dishDtoList.get(i).getId().toString());
                    cell.setCellStyle(cellStyleRow2);

                    //名称
                    cell = row2.createCell(1);
                    cell.setCellValue(dishDtoList.get(i).getName());
                    cell.setCellStyle(cellStyleRow2);

                    //图片
                    ExcelUtils.insertImage(basePath+dishDtoList.get(i).getImage(),workbook,sheet,currentRow,2);

                    //分类名称
                    cell = row2.createCell(3);
                    cell.setCellValue(dishDtoList.get(i).getCategoryName());
                    cell.setCellStyle(cellStyleRow2);

                    //售价
                    cell = row2.createCell(4);
                    cell.setCellValue(dishDtoList.get(i).getPrice().intValue()/100);
                    cell.setCellStyle(cellStyleRow2);

                    //口味
                    String flavorValue = "";
                    for (DishFlavor flavor : dishDtoList.get(i).getFlavors()) {
                        flavorValue = flavorValue +flavor.getName()+":"+flavor.getValue()+"\r\n";
                    }
                    cell = row2.createCell(5);
                    cell.setCellValue(flavorValue);
                    cell.setCellStyle(cellStyleRow2);

                    //描述
                    cell = row2.createCell(6);
                    cell.setCellValue(dishDtoList.get(i).getDescription());
                    cell.setCellStyle(cellStyleRow2);

                    //状态
                    String statusValue = "";
                    if (dishDtoList.get(i).getStatus() == 1){
                        statusValue = "启售";
                    }else {
                        statusValue = "停售";
                    }
                    cell = row2.createCell(7);
                    cell.setCellValue(statusValue);
                    cell.setCellStyle(cellStyleRow2);

                    //最后操作时间
                    cell = row2.createCell(8);
                    cell.setCellValue(dishDtoList.get(i).getUpdateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    cell.setCellStyle(cellStyleRow2);
                }
            }

//            workbook.write(new FileOutputStream("D:/黑马java培训班/菜品表.xlsx"));

            //通过浏览器下载

        }catch (Exception e){
            throw new CustomException("生成失败");
        }


        return workbook;
    }




    public String deleteImageByDishId(Long id){
        String imageName = dishMapper.findImageNameById(id);
        File image = new File(basePath+imageName);
        String result;
        if (image.exists()){
            //存在
            if (image.delete()){
                //删除成功
                result = "图片"+image+"删除成功";
            }else {
                result="删除失败";
            }
        }else {
            result="文件不存在";
        }
        log.info(result);
        return result;
    }
}
